#include "loger.h"
#include "loger_inner.h"
#include <stdarg.h>

/* loger 日志 */

#if (CONFIG_LOGER_ENABLE == 1)

#define LOGER_LEVEL             CONFIG_LOGER_LEVEL
#define LOGER_COLOR             CONFIG_LOGER_COLOR
#define LOGER_LINE_BUFF_SIZE    CONFIG_LOGER_LINE_BUFF_SIZE

#define LOGER_CSI_START         "\033[0;"
#define LOGER_CSI_END           "\033[0m"

typedef struct 
{
    uint8_t output_en;
    uint8_t level;
    uint8_t text_color_en;
    char buff[LOGER_LINE_BUFF_SIZE];
} _loger_cfg_obj;

/* static var */

extern const _loger_fmt_info_t loger_fmt_info_t[];
static _loger_cfg_obj loger_cfg_obj;


/* static func */




/* export func */


/**
 * @brief 初始化
 * 
 * @return int 
 */
int loger_init(void)
{
    int ret;

    memset(&loger_cfg_obj, 0x00, sizeof(_loger_cfg_obj));
    loger_cfg_obj.output_en = 1;
    loger_cfg_obj.level = LOGER_LEVEL;
    loger_cfg_obj.text_color_en = (uint8_t)LOGER_COLOR;

    ret = loger_port_init();
    if (ret)
    {
        return ret;
    }

    return 0;
}

/**
 * @brief 原始输出
 * 
 * @param format 
 * @param ... 
 */
void loger_raw(const char *format, ...)
{
    uint32_t log_len;
    int fmt_ret;
    va_list args;

    if (loger_cfg_obj.output_en == 0)
    {
        return ;
    }

    loger_port_lock();

    log_len = 0;
    va_start(args, format);
    fmt_ret = vsnprintf(loger_cfg_obj.buff, LOGER_LINE_BUFF_SIZE, format, args);
    if ((fmt_ret>-1) && (fmt_ret<=LOGER_LINE_BUFF_SIZE))
    {
        log_len = fmt_ret;
    }
    else
    {
        log_len = LOGER_LINE_BUFF_SIZE;
    }
    va_end(args);

    if ((log_len+2) > LOGER_LINE_BUFF_SIZE)
    {
        log_len = LOGER_LINE_BUFF_SIZE - 2;
    }
    log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, "\r\n");
    
    loger_port_output(loger_cfg_obj.buff, log_len);

    loger_port_unlock();
}

/**
 * @brief 日志格式输出
 * 
 * @param level 登记 [A],[E],[W],[I],[D],[V]
 * @param tag 标签 xx: 
 * @param file 所在文件
 * @param func 所在函数
 * @param line 所在文件行
 * @param format 
 * @param ... 
 */
void loger_output(uint8_t level, const char *tag, const char *file, const char *func, const long line,
                  const char *format, ...)
{
    uint32_t log_len;
    int fmt_ret;
    va_list args;
    _loger_fmt_info_t *pfmt;

    /* user config output enable */
    if (loger_cfg_obj.output_en == 0)
    {
        return ;
    }

    /* user config output level */
    if (level > loger_cfg_obj.level)
    {
        return ;
    }

    loger_port_lock();
    
    log_len = 0;
    memset(loger_cfg_obj.buff, 0x00, sizeof(loger_cfg_obj.buff));
    if (level > LOG_LV_VERBOSE) level = LOG_LV_VERBOSE;
    pfmt = (_loger_fmt_info_t*)&loger_fmt_info_t[level];

    va_start(args, format);

    /* add CSI start sign and color info */
#if (CONFIG_LOGER_COLOR == 1)
    if (loger_cfg_obj.text_color_en)
    {
        log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, LOGER_CSI_START);
        log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, pfmt->color_txt); //\033[0;31m
    }
#endif

    /* add level info [x] */
    log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, pfmt->head);

    /* add tag info */
    log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, tag);
    log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, ": ");

    /* add log data */
    fmt_ret = vsnprintf(loger_cfg_obj.buff+log_len, LOGER_LINE_BUFF_SIZE-log_len, format, args);
    if ((log_len + fmt_ret <= LOGER_LINE_BUFF_SIZE) && (fmt_ret > -1)) log_len += fmt_ret;
    else log_len = LOGER_LINE_BUFF_SIZE;

    va_end(args);

    /* add CSI end sign */
#if (CONFIG_LOGER_COLOR == 1)
    if ((log_len + sizeof(LOGER_CSI_END)) >= LOGER_LINE_BUFF_SIZE)
    {
        log_len = LOGER_LINE_BUFF_SIZE - sizeof(LOGER_CSI_END);
        log_len -= 2;   //"\r\n"
    }
    if (loger_cfg_obj.text_color_en)
    {
        log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, LOGER_CSI_END);
    }
#else
    if ((log_len + 1) >= LOGER_LINE_BUFF_SIZE)
    {
        log_len = LOGER_LINE_BUFF_SIZE;
        log_len -= 2;   // "\r\n" 
    }
#endif
   
    /* package newline sign */
    log_len += loger_strcpy(log_len, loger_cfg_obj.buff+log_len, "\r\n");

    /* output */
    loger_port_output(loger_cfg_obj.buff, log_len);

    loger_port_unlock();
}

/**
 * @brief 设置输出登记
 * 
 * @param lv 
 */
void loger_set_level(uint8_t lv)
{
    if (lv >= LOG_LV_MAX) lv = LOG_LV_MAX - 1;
    loger_cfg_obj.level = lv;
}

/**
 * @brief 设置输出文本颜色
 * 
 * @param en 
 */
void loger_set_text_color_enable(uint8_t en)
{
    if (en) loger_cfg_obj.text_color_en = 1;
    else loger_cfg_obj.text_color_en = 0;
}


#endif
